﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

using NUnit.Framework;

using Microsoft.Practices.Unity;

using ERPStore.Tests.Controllers;
using ERPStore.Web.Html;
using ERPStore.Tests;
using ERPStore.Web.Extensions;
using ERPStore.Extensions;

namespace ERPStore.Cart.Tests.Controllers
{
	/// <summary>
	/// Summary description for CartControllerTests
	/// </summary>
	[TestFixture]
	public class CartControllerTests : ERPStore.Tests.TestBase
	{
		public CartControllerTests()
		{
		}

		[SetUp]
		public override void Initialize()
		{
			base.Initialize();
		}

		[TearDown]
		public virtual void TearDown()
		{
			base.TeardownHttpContext();
		}

		private ERPStore.Web.Cart.Controllers.CartController CreateCartController()
		{
			var result = CreateController<ERPStore.Web.Cart.Controllers.CartController>();
			return result;
		}

		private ERPStore.Web.Cart.Controllers.CartController CreateCartControllerWithReferer()
		{
			var httpContext2 = GetHttpContext();
			var mock = Moq.Mock.Get(httpContext2.Request);
			mock.Setup(req => req.UrlReferrer).Returns(new Uri("http://www.referer.com"));
			var controller = CreateController<ERPStore.Web.Cart.Controllers.CartController>();
			return controller;
		}

		[Test]
		public virtual void Index()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");

			var result = (System.Web.Mvc.ViewResult)m_Controller.Index();
			var currentCart = result.ViewData.Model as ERPStore.Models.OrderCart;

			Assert.IsNotNull(currentCart);
		}

		[Test]
		public virtual void Empty_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.ViewResult)m_Controller.Index();
			Assert.AreEqual(result.ViewName, "EmptyCart");
		}

		[Test]
		public virtual void Add_Product_To_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.RedirectToRouteResult)m_Controller.AddCartItem("XBOX360");

			Assert.AreEqual(result.RouteName, Web.Cart.Routes.CART);

			var viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var currentCart = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.IsNotNull(currentCart);
			Assert.AreEqual(currentCart.ItemCount, 1);
			Assert.AreEqual(currentCart.Total, 199.99);
			Assert.AreEqual(currentCart.TotalTax, Convert.ToDecimal(199.99 * 0.196));
		}

		[Test]
		public virtual void Add_Same_Product_To_Cart()
		{
			var m_Controller = CreateCartController();
			var visitorId = ((ERPStore.Models.UserPrincipal) m_Controller.User).VisitorId;
			var result = (System.Web.Mvc.RedirectToRouteResult)m_Controller.AddCartItem("XBOX360");

			Assert.AreEqual(result.RouteName, Web.Cart.Routes.CART);

			var viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var currentCart = viewResult.Model as ERPStore.Models.OrderCart;
			Assert.AreEqual(currentCart.VisitorId , visitorId);

			Assert.IsNotNull(currentCart);
			Assert.AreEqual(currentCart.ItemCount, 1);
			Assert.AreEqual(currentCart.Total, 199.99);
			Assert.AreEqual(currentCart.TotalTax, Convert.ToDecimal(199.99 * 0.196));
			
			result = (System.Web.Mvc.RedirectToRouteResult)m_Controller.AddCartItem("XBOX360");

			Assert.AreEqual(result.RouteName, Web.Cart.Routes.CART);

			viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			currentCart = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.AreEqual(currentCart.ItemCount, 1);
			Assert.AreEqual(currentCart.Total, 199.99 * 2);
			Assert.AreEqual(currentCart.TotalTax, Convert.ToDecimal(199.99 * 0.196 * 2));
		}


		[Test]
		public virtual void Add_Product_To_Cart_With_Referer()
		{
			var m_ControllerWithReferer = CreateCartControllerWithReferer();
			var result = (System.Web.Mvc.RedirectToRouteResult)m_ControllerWithReferer.AddCartItem("XBOX360");

			Assert.AreEqual(result.RouteName, Web.Cart.Routes.CART);

			var viewResult = m_ControllerWithReferer.Index() as System.Web.Mvc.ViewResult;
			var currentCart = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.IsNotNull(currentCart);
			Assert.AreEqual(currentCart.ItemCount, 1);
			Assert.AreEqual(currentCart.Total, 199.99);
			Assert.AreEqual(currentCart.TotalTax, Convert.ToDecimal(199.99 * 0.196));
		}


		[Test]
		public virtual void Add_FakeProductCode_To_Cart()
		{
			var m_Controller = CreateCartController();
			var result = m_Controller.AddCartItem(Guid.NewGuid().ToString()) as RedirectToRouteResult;
			Assert.IsNotNull(result);

			Assert.AreEqual(result.RouteName, ERPStore.Web.Routing.ERPStoreRoutes.HOME);
		}

		[Test]
		public virtual void JSAdd_To_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.JsonResult)m_Controller.JsAddItem("XBOX360",null);
			Assert.IsNotNull(result.Data);
		}

		[Test]
		public virtual void JSAdd_To_Cart_With_Referer()
		{
			var m_ControllerWithReferer = CreateCartControllerWithReferer();
			var result = (System.Web.Mvc.JsonResult)m_ControllerWithReferer.JsAddItem("XBOX360", null);
			Assert.IsNotNull(result.Data);
		}


		[Test]
		public virtual void JSAdd_Fake_Product_To_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.JsonResult)m_Controller.JsAddItem(Guid.NewGuid().ToString(), null);
			Assert.IsNull(result.Data);
		}

		[Test]
		public virtual void JSAdd_Product_With_Quantity_To_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.JsonResult)m_Controller.JsAddItemWithQuantity("XBOX360", 5, null);

			var json = result.Data;
			Assert.IsNotNull(result.Data);

			var quantity = json.GetType().GetProperty("quantity").GetValue(json, null);
			Assert.IsNotNull(quantity);
			Assert.AreEqual((int)quantity, 5);
		}


		[Test]
		public virtual void Clear_Cart()
		{
			var m_Controller = CreateCartController();
			var result = m_Controller.AddCartItem("XBOX360") as System.Web.Mvc.RedirectToRouteResult;

			var clearResult = m_Controller.Clear() as System.Web.Mvc.ViewResult;
			Assert.AreEqual(clearResult.ViewName, "EmptyCart");

			var indexResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var currentCart = indexResult.Model as ERPStore.Models.OrderCart;

			Assert.AreEqual(currentCart.ItemCount, 0);
		}

		[Test]
		public virtual void Clear_Empty_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.ViewResult)m_Controller.Clear();

			Assert.IsNull(result.ViewData.Model);
			Assert.AreEqual(result.ViewName, "EmptyCart");
		}

		[Test]
		public virtual void Recalc_Empty_Cart()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			var result = (System.Web.Mvc.ViewResult)m_Controller.Recalc(null);
			Assert.IsNotNull(result.ViewData.Model);
			Assert.AreEqual(result.ViewName, "Index");
		}

		[Test]
		public virtual void Recalc_Existing_Cart()
		{
			var formCollection = new FormCollection();
			formCollection.Add("quantity", "5");
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			var result = (System.Web.Mvc.ViewResult)m_Controller.Recalc(formCollection);
			var cart = result.ViewData.Model as ERPStore.Models.OrderCart;
			Assert.IsNotNull(cart);
			Assert.AreEqual(result.ViewName, "Index");

			var item = cart.Items.First();

			Assert.AreEqual(item.Quantity, 5);
		}

		[Test]
		public virtual void Recalc_Existing_Cart_With_Bad_Data()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			var formCollection = new FormCollection();
			formCollection.Add("quantity", "a");
			var result = (System.Web.Mvc.ViewResult)m_Controller.Recalc(formCollection);
			var cart = result.ViewData.Model as ERPStore.Models.OrderCart;
			Assert.IsNotNull(cart);
			Assert.AreEqual(result.ViewName, "Index");

			var item = cart.Items.First();

			Assert.AreEqual(item.Quantity, 1);
		}


		[Test]
		public virtual void Recalc_Existing_Cart_With_Bad_Quantity()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			var formCollection = new FormCollection();
			formCollection.Add("quantity", "xxx");
			var result = (System.Web.Mvc.ViewResult)m_Controller.Recalc(formCollection);
			var cart = result.ViewData.Model as ERPStore.Models.OrderCart;
			Assert.IsNotNull(cart);
			Assert.AreEqual(result.ViewName, "Index");

			var item = cart.Items.First();

			Assert.AreEqual(item.Quantity, 1);
		}

		[Test]
		public virtual void Recalc_Existing_Cart_With_2_Items()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			m_Controller.AddCartItem("XBOXWC");
			var formCollection = new FormCollection();
			formCollection.Add("quantity", "5,4");
			var result = (System.Web.Mvc.ViewResult)m_Controller.Recalc(formCollection);
			var cart = result.ViewData.Model as ERPStore.Models.OrderCart;
			Assert.IsNotNull(cart);

			var item1 = cart.Items.First();
			var item2 = cart.Items[1];

			Assert.AreEqual(item1.Quantity, 5);
			Assert.AreEqual(item2.Quantity, 4);

			Assert.AreEqual(result.ViewName, "Index");
		}

		[Test]
		public virtual void Remove_Item_To_Empty_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.RedirectToRouteResult)m_Controller.RemoveItem(0);
			Assert.AreEqual(result.RouteName, ERPStore.Web.Routing.ERPStoreRoutes.HOME);
		}

		[Test]
		public virtual void Remove_Only_One_Item_To_Cart()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			var result = (System.Web.Mvc.ViewResult)m_Controller.RemoveItem(0);

			var cart = result.ViewData.Model as ERPStore.Models.OrderCart;
			Assert.IsNull(cart);

			Assert.AreEqual(result.ViewName, "EmptyCart");
		}

		[Test]
		public virtual void Remove_Item_From_Cart_With_Bad_Index()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			var result = m_Controller.RemoveItem(2) as System.Web.Mvc.RedirectResult;


			Assert.IsNotNull(result.Url);
		}

		[Test]
		public virtual void Remove_Item_From_Cart()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			m_Controller.AddCartItem("XBOXWC");

			var removeResult = m_Controller.RemoveItem(0) as System.Web.Mvc.RedirectResult;

			var indexResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var cart = indexResult.ViewData.Model as ERPStore.Models.OrderCart;
			var currentCartUrl = m_Controller.Url.CurrentCartHref(cart);
			Assert.AreEqual(removeResult.Url, currentCartUrl);

			Assert.IsNotNull(cart);

			Assert.AreEqual(cart.ItemCount, 1);

			var item = cart.Items.First();

			Assert.AreEqual(item.Product.Code, "XBOXWC");
		}

		[Test]
		public virtual void Delete_Cart()
		{
			var m_Controller = CreateCartController();

			var result = m_Controller.AddCartItem("XBOX360") as System.Web.Mvc.RedirectToRouteResult;

			var viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var currentCart = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.IsNotNull(currentCart);

			var result2 = (System.Web.Mvc.RedirectToRouteResult)m_Controller.Delete(currentCart.Code);
			Assert.AreEqual(result2.RouteName, Web.Cart.Routes.CART);
		}

		[Test]
		public virtual void Change_Cart()
		{
			var m_Controller = CreateCartController();

			var result = m_Controller.AddCartItem("XBOX360") as System.Web.Mvc.RedirectToRouteResult;
			var viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var cart1 = viewResult.Model as ERPStore.Models.OrderCart;

			m_Controller.Create();

			viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var cart2 = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.AreNotSame(cart1, cart2);

			var result2 = (System.Web.Mvc.RedirectToRouteResult)m_Controller.Change(cart1.Code);
			Assert.AreEqual(result2.RouteName, Web.Cart.Routes.CART);

			 viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var cart3 = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.AreEqual(cart1.Code, cart3.Code);
		}

		[Test]
		public virtual void Show_Empty_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.ViewResult)m_Controller.Show(null);
			Assert.AreEqual(result.ViewName, "EmptyCart");
		}

		[Test]
		public virtual void Show_Cart()
		{
			var m_Controller = CreateCartController();

			var result = m_Controller.AddCartItem("XBOX360") as System.Web.Mvc.RedirectToRouteResult;
			var viewResult = m_Controller.Index() as System.Web.Mvc.ViewResult;
			var cart = viewResult.Model as ERPStore.Models.OrderCart;

			var result2 = m_Controller.Show(cart.Code) as System.Web.Mvc.ViewResult;

			Assert.AreEqual(result2.ViewName, "Index");
			Assert.IsNotNull(cart);
		}

		[Test]
		public virtual void Create_Cart()
		{
			var m_Controller = CreateCartController();
			var result = (System.Web.Mvc.RedirectToRouteResult)m_Controller.Create();
			Assert.AreEqual(result.RouteName, ERPStore.Web.Routing.ERPStoreRoutes.HOME);
		}

		[Test]
		public virtual void Show_Current_Empty_Cart_List()
		{
			var m_Controller = CreateCartController();
            var result = (System.Web.Mvc.PartialViewResult)m_Controller.ShowCurrentCartList("test");
			var list = result.ViewData.Model as List<ERPStore.Models.OrderCart>;
			Assert.AreEqual(result.ViewName, "test");
			Assert.AreEqual(list.Count, 0);
		}

		[Test]
		public virtual void Show_Current_Cart_List()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
			var result = (System.Web.Mvc.PartialViewResult)m_Controller.ShowCurrentCartList("test");
			var list = result.ViewData.Model as List<ERPStore.Models.OrderCart>;
			Assert.AreEqual(result.ViewName, "test");
			Assert.AreEqual(list.Count, 1);
		}

		[Test]
		public virtual void Show_Status_Empty()
		{
			var m_Controller = CreateCartController();
            var result = (System.Web.Mvc.PartialViewResult)m_Controller.ShowStatus("test");
			var cart = result.ViewData.Model as ERPStore.Models.OrderCart;
			Assert.IsNull(cart);
			Assert.AreEqual(result.ViewName, "test");
		}

		[Test]
		public virtual void Show_Status()
		{
			var m_Controller = CreateCartController();
			m_Controller.AddCartItem("XBOX360");
            var result = (System.Web.Mvc.PartialViewResult)m_Controller.ShowStatus("test");
			var cart = result.ViewData.Model as ERPStore.Models.OrderCart;
			Assert.IsNotNull(cart);
			Assert.AreEqual(result.ViewName, "test");
		}

		[Test]
		public virtual void Assign_Cart_To_New_Visitor()
		{
			var cartService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.ICartService>();
			var catalogService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.ICatalogService>();
			var offerService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.IOffersService>();

			var user = TestHelper.GetCustomerUserPrincipal();
			var visitorId = user.VisitorId;

			var cart = cartService.CreateCart(user);
			var product = catalogService.GetProductByCode("xbox360");

			offerService.ApplyOffers(product, user.CurrentUser);
			cartService.AddCartItem(cart, product, 1, "test", null, null);
			cartService.Save(cart);

			var m_Controller = CreateCartController();

			var assignResult = m_Controller.Assign(cart.Code) as System.Web.Mvc.RedirectResult;

			var url = string.Format("/panier/voir/{0}?estid=assign", cart.Code);
			Assert.AreEqual(url, assignResult.Url);

			var viewResult = m_Controller.Show(cart.Code) as System.Web.Mvc.ViewResult;
			cart = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.AreNotEqual(visitorId, cart.VisitorId);
			Assert.AreEqual(cart.ItemCount, 1);
		}

		[Test]
		public virtual void Assign_Cart_To_Connected_Visitor()
		{
			var cartService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.ICartService>();
			var catalogService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.ICatalogService>();
			var offerService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.IOffersService>();

			var user = TestHelper.GetCustomerUserPrincipal();
			var visitorId = user.VisitorId;

			var cart = cartService.CreateCart(user);
			var product = catalogService.GetProductByCode("xbox360");

			offerService.ApplyOffers(product, user.CurrentUser);
			cartService.AddCartItem(cart, product, 1, "test", null, null);
			cartService.Save(cart);

			var m_Controller = CreateAuthenticatedController<ERPStore.Web.Cart.Controllers.CartController>();

			var assignResult = m_Controller.Assign(cart.Code) as System.Web.Mvc.RedirectResult;

			var url = string.Format("/panier/voir/{0}?estid=assign", cart.Code);
			Assert.AreEqual(url, assignResult.Url);

			var viewResult = m_Controller.Show(cart.Code) as System.Web.Mvc.ViewResult;
			cart = viewResult.Model as ERPStore.Models.OrderCart;

			Assert.AreNotEqual(visitorId, cart.VisitorId);
			Assert.AreEqual(cart.ItemCount, 1);
		}


	}
}
